/*
参考链接:
v851s uart3 设置成普通串口收发:
https://bbs.aw-ol.com/topic/3281/v851s-uart3-%E8%AE%BE%E7%BD%AE%E6%88%90%E6%99%AE%E9%80%9A%E4%B8%B2%E5%8F%A3%E6%94%B6%E5%8F%91?_=1695448208832
*/

#include <stdio.h>     /*标准输入输出定义*/
#include <stdlib.h>    /*标准函数库定义*/
#include <unistd.h>    /*Unix标准函数定义*/
#include <sys/types.h> 
#include <sys/stat.h>  /*六文件控制定义*/
#include <fcntl.h>      /*PX终端控制定义*/
#include <termios.h>    
#include <errno.h>
#include <string.h> 

int OpenDev(char *name) {
    int fd = open(name, O_RDWR ); 
    if (-1 == fd)
        printf("Can not OPen(%s)!", name);
    return fd;
}

/*
 * @brief  设置串口通信速率
 * @param fd 类型 int打开串口的文件句柄长 
 * @param speed 类型 int 串口速度
 * @return void
*/
void set_speed(int fd, int speed) {

    int	i;
    int	status;
    struct termios Opt = {0};
    int speed_arr[] = {B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
    int name_arr[] = {230400,115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, };

    tcgetattr(fd, &Opt);

    for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) {
        if (speed == name_arr[i])
            break;
    }

    tcflush(fd, TCIOFLUSH);
    cfsetispeed(&Opt, speed_arr[i]);
    cfsetospeed(&Opt, speed_arr[i]);

    Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
    Opt.c_oflag &= ~OPOST;	/*Output*/

    status = tcsetattr(fd, TCSANOW, &Opt);
    if (status != 0) {
        printf("tcsetattr fd");
        return;
	}
	tcflush(fd, TCIOFLUSH);
 }

/**
*@brief	设置串口数据位，停止位和效验位
*@param fd	类型    int 打开的串口文件句柄
*@param  databits 类 型  int 数 据位	取值  为  7 或者8
*@param  stopbits 类 型  int 停 止位	取值为  1 或者2
*@param parity 类型 int 效验类型 取值为N,E,O,,S
 */
int set_Parity(int fd,int databits,int stopbits,int parity) {
	struct termios options;

    if ( tcgetattr( fd,&options) != 0) {
        perror("SetupSerial 1");
        return -1;
    }
    options.c_cflag &= ~CSIZE;
    switch (databits) /*设置数据位数*/
    {
        case 7:
        options.c_cflag |= CS7;
        break;
        case 8:
        options.c_cflag |= CS8;
        break;
        default:
        fprintf(stderr,"Unsupported data size\n");
        return -1;
    }
    switch (parity)	
    {	
        case 'n':	
        case 'N':	
            options.c_cflag &= ~PARENB;	/* Clear parity enable */
            options.c_iflag &= ~INPCK;	/* Enable parity checking */
            break;	
        case 'o':
        case 'O':
            options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
            options.c_iflag |= INPCK;	/* Disnable parity checking */
            break;
        case 'e':
        case 'E':
            options.c_cflag |= PARENB;	/* Enable parity */
            options.c_cflag &= ~PARODD;	/*	*/
            options.c_iflag |= INPCK;	/* Disnable parity checking */
            break;
        case 'S':
        case 's': /*as no parity*/
            options.c_cflag &= ~PARENB;
            options.c_cflag &= ~CSTOPB;break;
        default:
            fprintf(stderr,"Unsupported parity\n");
            return -1;
    }
    /* 设置停止位*/
    switch (stopbits)
    {
        case 1:
            options.c_cflag &= ~CSTOPB;
            break;
        case 2:
            options.c_cflag |= CSTOPB;
            break;
        default:
            fprintf(stderr,"Unsupported stop bits\n");
            return -1;
    }
    /* Set input parity option */
    if (parity != 'n')
        options.c_iflag |= INPCK;
    tcflush(fd,TCIFLUSH);
    options.c_cc[VTIME] = 150; /*	15 seconds*/
    options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
    if (tcsetattr(fd,TCSANOW,&options) != 0) {
        perror("SetupSerial 3");
        return -1;
    }
    return 0;
}

// void str_print(char *buf, int len) {
// 	int i;
// 	printf("HEX:\n\t");
// 	for (i=0; i<len; i++) {
// 		if (i%10 == 0)
// 			printf("\n");
// 		printf("0x%02x ", buf[i]);
// 	}
// 	printf("\nCHAR:\n\t");
	
// 	for (i=0; i<len; i++) {
// 		printf("%c", buf[i]);
// 	}
// 	printf("\n");
// }

int fd_uart3 = 0;

int	uart3_init(void){

	int ret;
	fd_set rd_fdset;
	struct timeval dly_tm;	// delay time in select()
	
    // fd = OpenDev(argv[PT_DEV_NAME]);
	fd_uart3 = OpenDev("/dev/ttyS3");
	if (fd_uart3 < 0){
        printf("\n串口 3 打开失败！\n");
        printf("Open /dev/ttyS3 failed!\n");
	    return -1;
    }
	
    // 设置波特率为 115200
	set_speed(fd_uart3, 115200);

    // 8 数据位，1 停止位，无校验
	if (set_Parity(fd_uart3,8,1,'N') == -1) {
		printf("Set Parity Error\n");
		return -1;
	}

    FD_ZERO(&rd_fdset);
    FD_SET(fd_uart3, &rd_fdset);
    
    dly_tm.tv_sec = 5;
    dly_tm.tv_usec = 0;
	
	// close(fd_uart3);
	return 0;
}

void uart3_send(char *data){

    // ret = select(fd+1, &rd_fdset, NULL, NULL, &dly_tm);
    // DBG("select() return %d, fd = %d", ret, fd);
    // if (ret <= 0)
    //     continue;

    // if (ret < 0) {
    //     printf("select(%s) return %d. [%d]: %s \n", argv[PT_DEV_NAME], ret, errno,
    //     strerror(errno));
    //     continue;
    // }

    // scanf("%s", data);
    write(fd_uart3, data, strlen(data));
    // memset(data, 0, 256);

    // ret = read(fd, buf, 256);
    // printf("Cnt%d: read(%s) return %d.\n", i, argv[PT_DEV_NAME], ret);
    // str_print(buf, ret);
    // write(fd, buf_s, 256);
    // DBG("send over %d\n");

    // return 0;
}
